require File.dirname(__FILE__)+"/../../test_helper"
require "starframe/sprite"

class StarFrame::Sprite::Animatable::Animation::Builder
  attr_accessor :target, :name, :options
  attr_accessor :animations, :current_frame, :max_frame, :mode
end

class TestStarFrameSpriteAnimatable < Test::Unit::TestCase
  class AnimationSprite < StarFrame::Sprite
    include StarFrame::Sprite::Animatable
    attr_accessor :animation_frame, :animation_max_frame, :animations, :animation_index, :animation_size, :options
    
    @texture = StarRuby::Texture.new(1, 1)
    
    animation :animation1 do
      frames [1, 2, 3], 2 do |c|
        self.alpha = c
      end
      frames [10, 20, 30], 2 do |c|
        self.angle = c
      end
      frame 2 do
        self.angle = 0
      end
    end
    animation :animation2, :loop => false do
      frames [11, 22, 33] do |c|
        self.angle = c
      end
      frame do
        self.angle = 0
      end
    end
  end
  
  class AnimationSpriteSub < AnimationSprite
    animation :animation3 do
    end
  end
  
  def test_include_exception
    source = <<-END
      class UneventableClass
        include StarFrame::Sprite::Animatable
      end
    END
    assert_raise(TypeError){ eval source }
  end
  
  def test_class_variables
    assert_equal 2,                AnimationSprite.animations.size
    
    assert_instance_of StarFrame::Sprite::Animatable::Animation::Builder, AnimationSprite.animations[:animation1]
    
    assert_equal({:loop => true},  AnimationSprite.animations[:animation1].options)
    assert_equal({:loop => false}, AnimationSprite.animations[:animation2].options)
    
    assert_equal 14, AnimationSprite.animations[:animation1].max_frame
    assert_equal  4, AnimationSprite.animations[:animation2].max_frame
    
    assert_kind_of Hash,  AnimationSprite.animations[:animation1].animations
    assert_equal   7,     AnimationSprite.animations[:animation1].animations.size
    assert_kind_of Array, AnimationSprite.animations[:animation1].animations[ 0]
    assert_equal   1,     AnimationSprite.animations[:animation1].animations[ 0].size
    assert_kind_of Array, AnimationSprite.animations[:animation1].animations[ 2]
    assert_equal   1,     AnimationSprite.animations[:animation1].animations[ 2].size
    assert_kind_of Array, AnimationSprite.animations[:animation1].animations[ 4]
    assert_equal   1,     AnimationSprite.animations[:animation1].animations[ 4].size
    assert_kind_of Array, AnimationSprite.animations[:animation1].animations[ 6]
    assert_equal   1,     AnimationSprite.animations[:animation1].animations[ 6].size
    assert_kind_of Array, AnimationSprite.animations[:animation1].animations[ 8]
    assert_equal   1,     AnimationSprite.animations[:animation1].animations[ 8].size
    assert_kind_of Array, AnimationSprite.animations[:animation1].animations[10]
    assert_equal   1,     AnimationSprite.animations[:animation1].animations[10].size
    assert_kind_of Array, AnimationSprite.animations[:animation1].animations[12]
    assert_equal   1,     AnimationSprite.animations[:animation1].animations[12].size
    assert_kind_of Hash,  AnimationSprite.animations[:animation2].animations
    assert_equal   4,     AnimationSprite.animations[:animation2].animations.size
    assert_kind_of Array, AnimationSprite.animations[:animation2].animations[ 0]
    assert_equal   1,     AnimationSprite.animations[:animation2].animations[ 0].size
    assert_kind_of Array, AnimationSprite.animations[:animation2].animations[ 1]
    assert_equal   1,     AnimationSprite.animations[:animation2].animations[ 1].size
    assert_kind_of Array, AnimationSprite.animations[:animation2].animations[ 2]
    assert_equal   1,     AnimationSprite.animations[:animation2].animations[ 2].size
    assert_kind_of Array, AnimationSprite.animations[:animation2].animations[ 3]
    assert_equal   1,     AnimationSprite.animations[:animation2].animations[ 3].size
    
    assert_equal :_starframe_sprite_animatable_animation__animation_animation1_frames_1, AnimationSprite.animations[:animation1].animations[ 0][0][0]
    assert_equal :_starframe_sprite_animatable_animation__animation_animation1_frames_1, AnimationSprite.animations[:animation1].animations[ 2][0][0]
    assert_equal :_starframe_sprite_animatable_animation__animation_animation1_frames_1, AnimationSprite.animations[:animation1].animations[ 4][0][0]
    assert_equal :_starframe_sprite_animatable_animation__animation_animation1_frames_2, AnimationSprite.animations[:animation1].animations[ 6][0][0]
    assert_equal :_starframe_sprite_animatable_animation__animation_animation1_frames_2, AnimationSprite.animations[:animation1].animations[ 8][0][0]
    assert_equal :_starframe_sprite_animatable_animation__animation_animation1_frames_2, AnimationSprite.animations[:animation1].animations[10][0][0]
    assert_equal :_starframe_sprite_animatable_animation__animation_animation1_frames_3, AnimationSprite.animations[:animation1].animations[12][0][0]
    assert_equal :_starframe_sprite_animatable_animation__animation_animation2_frames_1, AnimationSprite.animations[:animation2].animations[ 0][0][0]
    assert_equal :_starframe_sprite_animatable_animation__animation_animation2_frames_1, AnimationSprite.animations[:animation2].animations[ 1][0][0]
    assert_equal :_starframe_sprite_animatable_animation__animation_animation2_frames_1, AnimationSprite.animations[:animation2].animations[ 2][0][0]
    assert_equal :_starframe_sprite_animatable_animation__animation_animation2_frames_2, AnimationSprite.animations[:animation2].animations[ 3][0][0]
    
    assert_equal  1, AnimationSprite.animations[:animation1].animations[ 0][0][1]
    assert_equal  2, AnimationSprite.animations[:animation1].animations[ 2][0][1]
    assert_equal  3, AnimationSprite.animations[:animation1].animations[ 4][0][1]
    assert_equal 10, AnimationSprite.animations[:animation1].animations[ 6][0][1]
    assert_equal 20, AnimationSprite.animations[:animation1].animations[ 8][0][1]
    assert_equal 30, AnimationSprite.animations[:animation1].animations[10][0][1]
    assert_equal  0, AnimationSprite.animations[:animation1].animations[12][0][1]
    assert_equal 11, AnimationSprite.animations[:animation2].animations[ 0][0][1]
    assert_equal 22, AnimationSprite.animations[:animation2].animations[ 1][0][1]
    assert_equal 33, AnimationSprite.animations[:animation2].animations[ 2][0][1]
    assert_equal  0, AnimationSprite.animations[:animation2].animations[ 3][0][1]
  end
  def test_class_variables_subclass
    assert_equal     3,                          AnimationSpriteSub.animations.size
    assert_not_equal AnimationSprite.animations, AnimationSpriteSub.animations
  end
  
  def test_initialize
    sprite = AnimationSprite.new
    assert_equal 2, sprite.animations.size
    assert_equal({}, sprite.options)
    
    assert_instance_of StarFrame::Sprite::Animatable::Animation, sprite.animations[:animation1]
    
    assert_respond_to sprite, :_starframe_sprite_animatable_animation__animation_animation1_frames_1
    assert_respond_to sprite, :_starframe_sprite_animatable_animation__animation_animation1_frames_2
    assert_respond_to sprite, :_starframe_sprite_animatable_animation__animation_animation1_frames_3
    assert !defined?  sprite._starframe_sprite_animatable_animation__animation_animation1_frames_4
    assert_respond_to sprite, :_starframe_sprite_animatable_animation__animation_animation2_frames_1
    assert_respond_to sprite, :_starframe_sprite_animatable_animation__animation_animation2_frames_2
    assert !defined?  sprite._starframe_sprite_animatable_animation__animation_animation2_frames_3
  end
  
  def test_animation_reader
    sprite = AnimationSprite.new
    assert_equal sprite.animations[:animation1], sprite.animation(:animation1)
    assert_equal sprite.animations[:animation2], sprite.animation(:animation2)
  end
  
  class SingleAnimationSprite < StarFrame::Sprite
    attr_accessor :animation_frame, :options
    
    include StarFrame::Sprite::Animatable
    @texture = StarRuby::Texture.new(1, 1)
    
    animation :animation1 do
      frames [1, 2, 3] do |c|
        self.alpha = c
      end
    end
    animation :animation2 do
      frames [1, 2, 3, 4] do |c|
        self.angle = c
      end
    end
  end
  
  def test_update_animation
    sprite = SingleAnimationSprite.new
    
    [
      {:alpha => 1, :angle => 1},
      {:alpha => 2, :angle => 2},
      {:alpha => 3, :angle => 3},
      {:alpha => 1, :angle => 4},
      {:alpha => 2, :angle => 1},
      {:alpha => 3, :angle => 2},
      {:alpha => 1, :angle => 3},
      {:alpha => 2, :angle => 4},
      {:alpha => 3, :angle => 1},
      {:alpha => 1, :angle => 2},
      {:alpha => 2, :angle => 3},
      {:alpha => 3, :angle => 4},
      {:alpha => 1, :angle => 1},
    ].each do |options|
      sprite.call_update
      assert_equal options, sprite.options
    end
  end
  def test_start_stop
    sprite = SingleAnimationSprite.new
    
    sprite.call_update
    assert_equal({:alpha => 1, :angle => 1}, sprite.options)
    
    sprite.animation(:animation2).stop
    sprite.call_update
    assert_equal({:alpha => 2, :angle => 1}, sprite.options)
    
    sprite.animation(:animation2).start
    sprite.call_update
    assert_equal({:alpha => 3, :angle => 2}, sprite.options)
    
    sprite.animation(:animation2).rewind
    sprite.call_update
    assert_equal({:alpha => 1, :angle => 1}, sprite.options)
    
    sprite.call_update
    assert_equal({:alpha => 2, :angle => 2}, sprite.options)
    
    sprite.animation(:animation1).stop
    sprite.call_update
    assert_equal({:alpha => 2, :angle => 3}, sprite.options)
    
    sprite.animation(:animation1).restart
    sprite.call_update
    assert_equal({:alpha => 1, :angle => 4}, sprite.options)
    
    sprite.call_update
    assert_equal({:alpha => 2, :angle => 1}, sprite.options)
  end
end
